/*
 *  Copyright (c) 2025 Huawei Device Co., Ltd.
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */

import 'package:flutter/material.dart';

import 'constant.dart';
import 'geometry_transition_route.dart';
import 'hide_container.dart';

/// 与页面关联的布局入口
typedef CloseContainerBuilder = Widget Function(
    BuildContext context, VoidCallback action);

/// 开启的页面布局
typedef OpenContainerBuilder<S> = Widget Function(
    BuildContext context, PopActionCallback<S> action);

/// 执行页面出栈，并传递参数
typedef PopActionCallback<S> = void Function({S? returnValue});

/// 页面返回时的回调
typedef PushActionCallback<S> = void Function(S data);

/// 一镜到底动效容器
@optionalTypeArgs
class GeometryTransition<T extends Object?> extends StatefulWidget {
  /// 开启的页面
  final OpenContainerBuilder<T> openBuilder;

  /// 与页面关联的布局入口
  final CloseContainerBuilder closedBuilder;

  /// 是否支持点击启动动画
  final bool tappable;

  /// 是否使用导航路由
  final bool useRootNavigator;

  /// 动画时长
  final Duration transitionDuration;

  /// 设置入口布局圆角
  final BorderRadius closedRadius;

  /// 设置新页面展示过程圆角
  final BorderRadius openRadius;

  /// 页面返回时的回调
  final PushActionCallback? onPushCallback;

  /// 路由设置项
  final RouteSettings? routeSettings;

  const GeometryTransition({
    super.key,
    required this.openBuilder,
    required this.closedBuilder,
    this.onPushCallback,
    this.tappable = true,
    this.transitionDuration = Constant.defaultDuration,
    this.useRootNavigator = false,
    this.closedRadius = Constant.defaultBorderRadius,
    this.openRadius = Constant.defaultBorderRadius,
    this.routeSettings,
  });

  @override
  State<GeometryTransition<T?>> createState() => _GeometryTransitionState<T?>();
}

class _GeometryTransitionState<T> extends State<GeometryTransition<T?>> {
  final GlobalKey<HideContainerState> _hideContainerKey =
      GlobalKey<HideContainerState>();
  final GlobalKey _closedBuilderKey = GlobalKey();

  @override
  Widget build(BuildContext context) {
    return HideContainer(
      key: _hideContainerKey,
      child: GestureDetector(
          onTap: widget.tappable ? handleOpenContainer : null,
          child: Builder(
              key: _closedBuilderKey,
              builder: (BuildContext context) {
                return widget.closedBuilder(context, handleOpenContainer);
              })),
    );
  }

  Future<void> handleOpenContainer() async {
    final T? data =
        await Navigator.of(context, rootNavigator: widget.useRootNavigator)
            .push(GeometryTransitionRoute<T>(
      closedRadius: widget.closedRadius,
      openRadius: widget.openRadius,
      hideContainerKey: _hideContainerKey,
      closedBuilderKey: _closedBuilderKey,
      closedBuilder: widget.closedBuilder,
      openBuilder: widget.openBuilder,
      transitionDuration: widget.transitionDuration,
      useRootNavigator: widget.useRootNavigator,
      routeSettings: widget.routeSettings,
    ));
    widget.onPushCallback?.call(data);
  }
}
